package model.gameBoard;

import java.awt.Dimension;
import java.awt.Point;
import java.util.HashMap;
import java.util.Map;

import model.entities.IEntity;
import model.entities.LaserSource;
import model.entities.Mirror;
import model.entities.Wall;
import model.entities.targets.ITarget;

/**
 * This class represents the world game board.
 * An empty cell contains a null pointer.
 * 
 * @author ben
 *
 */
public class GameBoard {
	
	private Dimension dimension;
	private IEntity[][] board;
	
	private Map<Point, LaserSource> sourceMap = new HashMap<Point, LaserSource>();
	
	/**
	 * Source map is needed, but the other maps are only here to 
	 * make the view rendering easier. If we wanted to remove these,
	 * we could have a paint method in the model entities. Right now
	 * I would rather do it this way.
	 */
	private Map<Point, Wall> wallMap = new HashMap<Point, Wall>();
	private Map<Point, Mirror> mirrorMap = new HashMap<Point, Mirror>();
	private Map<Point, ITarget> targetMap = new HashMap<Point, ITarget>();

	public GameBoard(Dimension dimension) {
		this.dimension = dimension;
		board = new IEntity[dimension.width][dimension.height];
	}
	
	public Map<Point, LaserSource> getSourceMap() {
		return sourceMap;
	}
	
	public boolean addEntity(IEntity entity, Point cell) {
		
		if (board[cell.x][cell.y] != null) { // cell filled
			return false;
		}
		
		board[cell.x][cell.y] = entity;
		return true;
		
	}
	
	public boolean addEntity(LaserSource source, Point cell) {
		
		if (board[cell.x][cell.y] != null) {
			return false;
		}
		
		board[cell.x][cell.y] = source;
		sourceMap.put(cell, source);
		
		return true;
		
	}
	
	public boolean addEntity(Mirror mirror, Point cell) {
		
		if (board[cell.x][cell.y] != null) {
			return false;
		}
		
		board[cell.x][cell.y] = mirror;
		mirrorMap.put(cell, mirror);
		
		return true;
		
	}
	
	public boolean addEntity(Wall wall, Point cell) {
		
		if (board[cell.x][cell.y] != null) {
			return false;
		}
		
		board[cell.x][cell.y] = wall;
		wallMap.put(cell, wall);
		
		return true;
		
	}
	
	public boolean addEntity(ITarget target, Point cell) {
		
		if (board[cell.x][cell.y] != null) {
			return false;
		}
		
		board[cell.x][cell.y] = target;
		targetMap.put(cell, target);
		
		return true;
		
	}
	
	public void removeEntity(Point cell) {
		board[cell.x][cell.y] = null;
		sourceMap.remove(cell);
		mirrorMap.remove(cell);
		wallMap.remove(cell);
		targetMap.remove(cell);
	}
	
	public IEntity getEntityAtCell(Point cell) {
		return board[cell.x][cell.y];
	}
	
	public Dimension getDimension() {
		return this.dimension;
	}

	public Map<Point, Wall> getWallMap() {
		return wallMap;
	}

	public Map<Point, Mirror> getMirrorMap() {
		return mirrorMap;
	}

	public Map<Point, ITarget> getTargetMap() {
		return targetMap;
	}

}
